import os
from singleton import singleton
from Services.Service import ServicePool

class VirtualFile:
    def __init__(self, content=None):
        self._content = content or ""

    def read(self):
        return self._content

    def write(self, content):
        self._content = content

class FileAccessError(Exception):
    def __init__(self, file_name):
        self.file_name = file_name
        super().__init__(f"Acess denied for file '{file_name}'") # Если доступ запрещен

class SecureFile:
    def __init__(self, file_name, readable=True, writable=True, openable=True):
        self.file_name = file_name
        self.readable = readable
        self.writable = writable
        self.openable = openable

@singleton
class FileActionManager:
    files = {}
    def __init__(self) -> None:
        service_pool = ServicePool()

        # Получаем данные из таблицы "files"
        success, result = service_pool.CallService("Registry", ("get_all_records", "files"))
        if success:
            files_data = result
        else:
            print(f"Error getting files data from registry: {result}")
            return
        #print(files_data)

        # Обновляем данные о файлах
        self.files = {}
        for file_name, file_data in files_data.items():
            readable = file_data.get("readable", True)
            writable = file_data.get("writable", True)
            openable = file_data.get("openable", True)
            self.files[file_name] = SecureFile(file_name, readable, writable, openable)

        #print("Files data loaded from registry successfully")
        #print(self.files)

    def SaveFileProperties(self):
        service_pool = ServicePool()
        # Проверяем наличие таблицы "files"
        success, result = service_pool.CallService("Registry", ("get_tables",))
        if success:
            tables = result
        else:
            #print(f"Error getting tables list: {result}")
            return

        if "files" not in tables:
            # Создаем таблицу "files", если ее нет
            success, result = service_pool.CallService("Registry", ("create_table", "files"))
            if not success:
                #print(f"Error creating 'files' table: {result}")
                return

        # Сохраняем данные о файлах в таблицу "files"
        files_data = {file_name: {"readable": file_obj.readable,
                                "writable": file_obj.writable,
                                "openable": file_obj.openable}
                    for file_name, file_obj in self.files.items()}
        #print(files_data)
        success, result = service_pool.CallService("Registry", ("insert", "files", files_data))

    def ResolvePath(self, rel_path):
        base_path = os.getcwd() # base_path = "C:/Users/igovn/Documents/qubic_eal" - у винды вместо / стоит \. поэтому не будет работать в винде
        base_parts = base_path.split('/')
        rel_parts = rel_path.split('/')
        
        for part in rel_parts:
            if part == '..':
                if base_parts:
                    base_parts.pop()
            elif part != '.' and part != '':
                base_parts.append(part)
        
        abs_path = '/'.join(base_parts)
        return abs_path

    def GetFile(self, file_name):
        file_name = self.ResolvePath(file_name)
        #print(file_name)
        if file_name not in self.files:
            self.files[file_name] = SecureFile(file_name)
        return self.files[file_name]

    def SetAction(self, file_name, readable=None, writable=None, openable=None):
        file_obj = self.GetFile(file_name)
        if readable is not None:
            file_obj.readable = readable
        if writable is not None:
            file_obj.writable = writable
        if openable is not None:
            file_obj.openable = openable
        self.SaveFileProperties()

@singleton
class FileWizard:
    virt_files = {}
    def RegisterVirtualFile(self, name, file_class):
        virt_files[name] = file_class
    
    def RemoveVirtualFile(self, name):
        del virt_files[name]

    def custom_open(self, func):
        #denied = ["example.txt"] # Список запрещенных файлов
        def secure_open(file_name, mode='r', *args, **kwargs):
            #print(file_name)
            if file_name in self.virt_files: 
                #raise FileAccessError(file_name)
                return self.virt_files[file_name](file_name, mode, *args, **kwargs)
            
            file_obj = FileActionManager().GetFile(file_name)
            if not file_obj.openable:
                raise FileAccessError(file_obj.file_name) #, "opening")

            if not file_obj.readable and 'r' in mode:
                raise FileAccessError(file_obj.file_name) #, "reading")

            if not file_obj.writable and 'w' in mode:
                raise FileAccessError(file_obj.file_name) #, "writing")

            return func(file_name, mode, *args, **kwargs)

        def wrapper(file_name, mode = 'r', *args, **kwargs):
            return secure_open(file_name, mode, *args, **kwargs) # После прохождения обработки и условий, возвращаем объект файла

        return wrapper

open = FileWizard().custom_open(open)

